package com.usian.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usian.mapper.TbItemCatMapper;
import com.usian.mapper.TbItemDescMapper;
import com.usian.mapper.TbItemMapper;
import com.usian.mapper.TbItemParamItemMapper;
import com.usian.pojo.*;
import com.usian.redis.RedisClient;
import com.usian.service.ItemService;
import com.usian.utils.IDUtils;
import com.usian.utils.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private TbItemMapper tbItemMapper;

    @Autowired
    private TbItemDescMapper tbItemDescMapper;

    @Autowired
    private TbItemParamItemMapper tbItemParamItemMapper;

    @Autowired
    private TbItemCatMapper tbItemCatMapper;

    @Value("${ITEM_INFO}")
    private String ITEM_INFO;

    @Value("${BASE}")
    private String BASE;

    @Value("${DESC}")
    private String DESC;

    @Value("${PARAM}")
    private String PARAM;

    @Value("${ITEM_INFO_EXPIRE}")
    private Integer ITEM_INFO_EXPIRE;

    @Value("${SETNX_BASC_LOCK_KEY}")
    private String SETNX_BASC_LOCK_KEY;

    @Value("${SETNX_DESC_LOCK_KEY}")
    private String SETNX_DESC_LOCK_KEY;


    @Value("${SETNX_PARAM_LOCK_KEY}")
    private String  SETNX_PARAM_LOCK_KEY;

    @Autowired
    private RedisClient redisClient;


    @Override
    public TbItem selectItemInfo(Long id) {
        //查询缓存
        TbItem tbItem = (TbItem) redisClient.get(ITEM_INFO + ":" + id + ":" + BASE);
        if (tbItem != null) {
            return tbItem;
        }
        //        解决缓存穿透
        if (redisClient.setnx(SETNX_BASC_LOCK_KEY+":"+id,id,30L)){
            tbItem = tbItemMapper.selectByPrimaryKey(id);
            if (tbItem != null) {

                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + id + ":" + BASE, tbItem);
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + id + ":" + BASE, ITEM_INFO_EXPIRE);
            }else {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + id + ":" + BASE, null);
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + id + ":" + BASE, 30);
            }
            redisClient.del(SETNX_BASC_LOCK_KEY+":"+id);
            return tbItem;
        }else {
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
            return selectItemInfo(id);
        }

    }

    @Override
    public PageResult selectTbItemAllByPage(Integer page, Integer rows) {
        /*page当前页    rows总页数*/
        PageHelper.startPage(page, rows);
        /*利用example的status当存在时展示所有*/
        TbItemExample example = new TbItemExample();
        TbItemExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo((byte) 1);
        /*根据id倒序*/
        example.setOrderByClause("id desc");
        List<TbItem> list = tbItemMapper.selectByExample(example);
        /*封装list得到pageinfo*/
        PageInfo<TbItem> pageInfo = new PageInfo<>(list);
        /*传参*/
        return new PageResult(pageInfo.getPageNum(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Integer insertTbItem(TbItem tbItem, String desc, String itemParams) {
        //补齐tbitem数据
        long itemId = IDUtils.genItemId();
        Date date = new Date();
        tbItem.setId(itemId);
        tbItem.setStatus((byte) 1);
        tbItem.setCreated(date);
        tbItem.setUpdated(date);
        tbItem.setPrice(tbItem.getPrice() * 100);/*因为数据库存储是以分为单位所以*100 */
        Integer tbItemNum = tbItemMapper.insertSelective(tbItem);/*添加商品表*/
        //补齐商品描述对象
        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(itemId);
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setCreated(date);
        tbItemDesc.setUpdated(date);
        Integer tbItemDescNum = tbItemDescMapper.insertSelective(tbItemDesc);/*添加商品描述对象*/
        //补齐商品规格参数
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        tbItemParamItem.setItemId(itemId);
        tbItemParamItem.setParamData(itemParams);
        tbItemParamItem.setUpdated(date);
        tbItemParamItem.setCreated(date);
        Integer itemParamItemNum = tbItemParamItemMapper.insertSelective(tbItemParamItem);/*添加商品规格参数*/
        return tbItemNum + tbItemDescNum + itemParamItemNum;

    }

    @Override
    public Map<String, Object> preUpdateItem(Long itemId) {
        /*获取map键值对*/
        Map<String, Object> map = new HashMap<>();
        /*根据id查询商品信息*/
        TbItem item = tbItemMapper.selectByPrimaryKey(itemId);
        /*添加到map集合中*/
        map.put("item", item);
        /*根据id查询商品描述对象*/
        TbItemDesc itemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
        /*传入值，itemDesc对象，但后边是itenDesc表中的描述信息（因为他只回显描述对象就可以）*/
        map.put("itemDesc", itemDesc.getItemDesc());
        /*获取商品种类信息*/
        TbItemCat itemCat = tbItemCatMapper.selectByPrimaryKey(item.getCid());
        /*回显你所选择的商品信息名字所以传传入他的name*/
        map.put("itemCat", itemCat.getName());
        /*当获取到的商品种类信息有下边的消息时，根据example方法得到信息并回显*/
        TbItemParamItemExample example = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        /**/
        List<TbItemParamItem> list = tbItemParamItemMapper.selectByExampleWithBLOBs(example);

        if (list != null && list.size() > 0) {
            /*判断后传值因为前台只需要回显itemParamItem中的ParamData() ， 所以传入让他回显*/
            map.put("itemParamItem", list.get(0).getParamData());
        }
        return map;
    }

    @Override
    public Integer updateTbItem(TbItem tbItem, String desc, String itemParams) {
        //补齐tbitem数据
        Date date = new Date();
        /*赋值修改时间*/
        tbItem.setUpdated(date);
        /*根据id修改商品表*/
        Integer tbItemNum = tbItemMapper.updateByPrimaryKeySelective(tbItem);
        //补齐商品描述对象
        /*获取商品描述对象*/
        TbItemDesc tbItemDesc = new TbItemDesc();
        /*赋值tbItemDesc中的tbItem_id*/
        tbItemDesc.setItemId(tbItem.getId());
        /*赋值desc*/
        tbItemDesc.setItemDesc(desc);
        /*赋值修改时间*/
        tbItemDesc.setUpdated(date);
        /*根据赋值的tbItem_id修改tbItemDesc表*/
        Integer tbItemDescNum = tbItemDescMapper.updateByPrimaryKeySelective(tbItemDesc);
        //补齐商品规格参数
        /*获取商品规格参数对象*/
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        /*赋值商品规格参数整的item_id*/
        tbItemParamItem.setItemId(tbItem.getId());
        /*赋值itemParams（这个是已经回显如果修改是根据这个参数进行修改）*/
        tbItemParamItem.setParamData(itemParams);
        /*赋值修改时间*/
        tbItemParamItem.setUpdated(date);
        /*传参没有TbItemParamItem中的id但是有商品表的id（itemId）所以利用example利用itemId来作为条件
         * */
        TbItemParamItemExample example = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(tbItemParamItem.getItemId());
        Integer tbItemParamNum = tbItemParamItemMapper.updateByExampleSelective(tbItemParamItem/*值*/, example/*条件*/);
        return tbItemNum + tbItemDescNum + tbItemParamNum;
    }

    @Override
    public Integer deleteItemById(Long itemId) {
        /*逻辑删除*/
        /*首先根据itemId查询到商品信息）*/
        TbItem tbItem = tbItemMapper.selectByPrimaryKey(itemId);
        /*利用status 修改状态为3（删除状态）*/
        tbItem.setStatus((byte) 3);
        /*最后展示你修改过的信息已被删除*/
        return tbItemMapper.updateByPrimaryKeySelective(tbItem);
    }

    @Override
    public TbItemDesc selectItemDescByItemId(Long itemId) {
        //查询缓存
        TbItemDesc tbItemDesc = (TbItemDesc) redisClient.get(ITEM_INFO + ":" + itemId + ":" + DESC);
        if (tbItemDesc != null) {
            return tbItemDesc;
        }
        if (redisClient.setnx(SETNX_DESC_LOCK_KEY+":"+itemId,itemId,30L)){
            TbItemDescExample example = new TbItemDescExample();
            TbItemDescExample.Criteria criteria = example.createCriteria();
            criteria.andItemIdEqualTo(itemId);
            List<TbItemDesc> tbItemDescList = tbItemDescMapper.selectByExample(example);

            if (tbItemDescList != null && tbItemDescList.size() > 0) {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + DESC, tbItemDescList.get(0));
                //设置有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + DESC, ITEM_INFO_EXPIRE);
                return tbItemDescList.get(0);
            }else {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + DESC, null);
                //设置有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + DESC, 30);
                return null;
            }
        }else {
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
            return selectItemDescByItemId(itemId);
        }
    }

    @Override
    public TbItemParamItem selectTbItemParamItemByItemId(Long itemId) {
        //查询缓存
        TbItemParamItem tbItemParamItem = (TbItemParamItem) redisClient.get(ITEM_INFO + ":" + itemId + ":" + PARAM);
        if (tbItemParamItem != null) {
            return tbItemParamItem;
        }
        if (redisClient.setnx( SETNX_PARAM_LOCK_KEY+":"+itemId,itemId,30L)){
            TbItemParamItemExample example = new TbItemParamItemExample();
            TbItemParamItemExample.Criteria criteria = example.createCriteria();
            criteria.andItemIdEqualTo(itemId);
            List<TbItemParamItem> tbItemParamItems = tbItemParamItemMapper.selectByExample(example);
            if (tbItemParamItems != null && tbItemParamItems.size() > 0) {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + PARAM, tbItemParamItems.get(0));
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + PARAM, ITEM_INFO_EXPIRE);
                return tbItemParamItems.get(0);
            }else {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + PARAM, null);
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + PARAM, 30);
                return null;
            }
        }else {
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
            return selectTbItemParamItemByItemId(itemId);
        }
    }
}
